﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Enterprise.Utils
{
    /// <summary>
    /// Provides Serialize, Deserialize conversions.
    /// </summary>
    public static class SerializeFactory
    {
        /// <summary>
        /// Converts string to byte[]
        /// </summary>
        /// <param name="str">String to return as byte[]</param>
        /// <returns>byted string</returns>
        public static byte[] StrToByteArray(string str)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetBytes(str);
        }

        /// <summary>
        /// Byte[] to string
        /// </summary>
        /// <param name="arr">The byte array to convert</param>
        /// <returns>Byte[] data to string</returns>
        public static string ByteArrayToStr(byte[] arr)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetString(arr, 0, arr.Length);
        }


        /// <summary>
        /// Encodes a string to byte[] in UTF8
        /// </summary>
        /// <param name="pXmlString"></param>
        /// <returns></returns>
        public static Byte[] StringToUTF8ByteArray(String xmlString)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] byteArray = encoding.GetBytes(xmlString);
            return byteArray;
        }


        /// <summary>
        /// Deserializes a string for a specifik type, T
        /// </summary>
        /// <param name="pXmlizedString">The string to deserialize</param>
        /// <param name="T">Deserialize to Type "T"</param>
        /// <returns></returns>
        public static Object DeserializeObject(String xmlizedString, Type T)
        {
            XmlSerializer xs = new XmlSerializer(T);
            MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(xmlizedString));
            XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
            return xs.Deserialize(memoryStream);
        }

        /// <summary>
        /// Serialize an Object
        /// </summary>
        /// <param name="obj">The object to serialize</param>
        /// <returns>A serialized string</returns>
        public static string SerializeObject(Object obj)
        {
            string serialXML;
            XmlSerializer xs = new XmlSerializer(obj.GetType());
            StringWriter sw = new StringWriterEncoding(Encoding.UTF8);
            try
            {
                xs.Serialize(sw, obj);
                serialXML = sw.ToString();
                sw.Close();
                return serialXML;
            }

            finally { sw.Dispose(); }
        }


        /// <summary>
        /// Overrides the the default StringWriter with Encoding.UTF8
        /// </summary>
        public class StringWriterEncoding : StringWriter
        {
            Encoding encoding;
            public StringWriterEncoding(Encoding encoding)
            {
                this.encoding = encoding;
            }

            public override Encoding Encoding
            {
                get { return encoding; }
            }
        }

        /// <summary>
        /// Binary deserialize byte[] data
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns>TypeOf(class)</returns>
        public static T BinaryDeserialize<T>(byte[] data)
        {
            byte[] bytes = data;
            MemoryStream mSteam = new MemoryStream(bytes);
            mSteam.Read(bytes, 0, bytes.Length);

            IFormatter formatter = new BinaryFormatter();
            mSteam.Seek(0, SeekOrigin.Begin);

            return (T)formatter.Deserialize(mSteam);
        }
    }
}
